﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Core.Entities;
using Core.IRepository;
using System.Linq.Expressions;
using Core.Queries;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using Core.Messages;
using Library.Extensions;

namespace Repositories
{
    public abstract class BaseRepository<TId, TEntity> : IBaseRepository<TId, TEntity>
        where TEntity : class
    {
        public DbContext Context;

        protected virtual DbSet<TEntity> DbSet 
        { 
            get 
            {
                return Context.Set<TEntity>();
            } 
        }

        public BaseRepository(DbContext Context)
        {
            this.Context = Context;
        }

        public virtual TEntity FindBy(TId id)
        {
            return DbSet.Find(id);
        }

        public virtual void Add(TEntity entity)
        {            
            DbSet.Add(entity);
        }

        public virtual void Edit(TEntity entity)
        {
            Context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
        }

        public void Delete(TEntity entity)
        {            
            DbSet.Remove(entity);
        }

        public void Delete(Expression<Func<TEntity, bool>> predicate)
        {
            var list = DbSet
               .Where(predicate)
               .ToList();

            foreach (TEntity entity in list)
            {
                DbSet.Remove(entity);                
            }
        }

        public IList<TEntity> FindBy(Expression<Func<TEntity, bool>> predicate)
        {
            var list = DbSet
                .Where(predicate)
                .ToList();

            return list;
        }

        public virtual ListResponse<TEntity> FindBy(BaseQuery<TEntity> query)
        {
            ListResponse<TEntity> response = new ListResponse<TEntity>();

            if (query.PagingEnabled && string.IsNullOrEmpty(query.SortColumn))
                throw new Exception("PagingEnabled enabled but SortColumn not defined");

            if (query.PagingEnabled && !string.IsNullOrEmpty(query.SortColumn))
            {
                var q = DbSet.Where(query.ToExpression()).AsQueryable();
                if (query.SortAscending)
                    q = q.OrderBy(query.SortColumn);
                else
                    q = q.OrderByDescending(query.SortColumn);

                response.List = q.Skip((query.PageNumber - 1) * query.PageSize).Take(query.PageSize)
                                .ToList();                

                if (query.ComputePagesCount)
                    response.RowsCount = DbSet.Where(query.ToExpression()).Count();
            }
            else
                response.List = DbSet.Where(query.ToExpression()).ToList();

            return response;
        }
    }


}
